free theorem
参考
gpt-5.icon
多相型(parametric polymorphism)をもつ関数の「型」だけから、その関数が必ず満たす性質を導ける定理のことです。
実装を一切見なくても、型が制約として振る舞う点が本質です。
直観的な考え方
多相関数は「型に関して中立」でなければなりません。
つまり、
特定の型に依存した分岐ができない
値の中身を勝手に作れない(引数にあるものしか使えない)
この制約から、「どう振る舞うか」が型だけで決まります。
基本例
例1: id
code:haskell
id :: forall a. a -> a
この型を持つ関数は何ができるか?
a の具体的な型は不明
新しい a を生成できない
引数を捨てると a を返せない
👉 結論
返せるのは「受け取った値そのもの」だけ。
free theorem
code:text
id x = x
例2: fmap 的な型
code:haskell
f :: forall a b. (a -> b) -> a -> b この関数は、
a の値を直接観察できない
(a -> b) を使うしか b を作れない
👉 つまり:
要素数を勝手に増やせない
各要素に関数を適用する以外のことはできない
free theorem(直感的表現)
code:text
f g = map g ∘ f id
(実質「map的な構造保存」を強制される)
数学的な定式化(ざっくり)
free theorem は parametricity(パラメトリシティ) から導かれます。
型変数 a を「任意の集合」
関数を「関係を保存する写像」
と解釈すると、
多相関数は、すべての型の間の関係を壊さない
という性質が得られ、そこから等式(定理)が導出されます。
典型的な制約パターン
table:_
型 必然的な振る舞い
forall a. a -> a 恒等関数
forall a. a -> Int 定数関数
forall a. [a] -> [a] 要素を並べ替える/削るだけ
forall a b. (a -> b) -> a -> b 関数適用
注意点
unsafeCoerce や Typeable のような 型情報を観測できる仕組み があると壊れる
副作用(IO、例外)を含むと成立しない場合がある
純粋・parametric であることが前提
関数がGenericに書かれているならば、それらの関数について一定の性質が満たされることが、(unit testとかで確認しなくても)保証される、という話です。具体的な型に落として関数を実装するのでなく、あえてGenericに書くことで得られる良い性質。tweet 何がfreeなん?
これってfunctor即の話?
定理
fmap :: (a -> b) -> F a -> F bは、
以下のような関数f、g、k、hが与えられたとき
code:hs
g . h = k . f
以下を満たす
code:hs
$map g . fmap h = fmap k . $map f
ここで、$mapはFに関する自然なmap
補題1
code:hs
fmap f = $map f
Functor則の1つ目と、free theoremから導出できる
補題2
code:hs
f . g = id . (f . g)
定理
code:hs
fmap f. fmap g = fmap (f . g)
Functor則の2つ目mrsekut.icon
証明
割と大変っぽい
code:hs
fmap id = id
fmap f . fmap g = fmap (f . g)
導出
https://gyazo.com/830db6c0e463c23342daec8794efc2ac
parametricだからこそ得られる性質である、的なことが書いてある